package com.gds.common.wechat.wechat.httpRequest;


import com.alibaba.fastjson.JSONObject;

import com.gds.common.wechat.wechat.WxPayUtil;
import com.gds.common.wechat.wechat.XMLUtil;
import com.gds.common.wechat.wechat.entities.PayNotifyResult;
import com.gds.common.wechat.wechat.entities.UnfiedOrderParam;
import com.gds.common.wechat.wechat.entities.UnfiedOrderResult;
import com.gds.common.wechat.wechat.enums.ReturnCodeEnum;
import com.gds.common.wechat.wechat.enums.WechatPayTradeTypeEnum;
import com.gds.utils.BizExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;


/****
 * 微信支付
 */
public class WechatPayHttpRequest {


    private static final String unifiedorderUri = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    private static RestTemplate restTemplate = new RestTemplate();
    private static Logger log = LoggerFactory.getLogger(WechatPayHttpRequest.class);

    static {
        List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
        converterList.remove(1);    //移除StringHttpMessageConverter
        HttpMessageConverter<?> converter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
        converterList.add(1, converter);    //convert顺序错误会导致失败
        restTemplate.setMessageConverters(converterList);
    }

    /***
     * 微信统一支付接口
     * @param unfiedOrderParam
     */
    public static UnfiedOrderResult unifiedorder(UnfiedOrderParam unfiedOrderParam, String key) throws Exception {
        SortedMap<Object, Object> param = new TreeMap<>();

        String nonceStr = System.currentTimeMillis() + "";
        //appid
        param.put("appid", unfiedOrderParam.getAppid());
        //商户码
        param.put("mch_id", unfiedOrderParam.getMch_id());
        //随机字符串
        param.put("nonce_str", nonceStr);
        //商品描述 格式:  腾讯公司-充值
        param.put("body", new String(unfiedOrderParam.getBody()));
        //订单号 需在应用系统中唯一
        param.put("out_trade_no", unfiedOrderParam.getOut_trade_no());
        //付款方式
        param.put("fee_type", unfiedOrderParam.getFee_type());
        //钱数  以分为单位
        param.put("total_fee", unfiedOrderParam.getTotal_fee());
        //终端 根据trade_type不同 ip取值不同
        param.put("spbill_create_ip", unfiedOrderParam.getSpbill_create_ip());
        //回调地址
        param.put("notify_url", unfiedOrderParam.getNotify_url());
        //交易类型
        param.put("trade_type", unfiedOrderParam.getTrade_type());
        if (!WechatPayTradeTypeEnum.扫码支付.getCode().equals(unfiedOrderParam.getTrade_type())) {
            //微信用户 openid
            param.put("openid", unfiedOrderParam.getOpenid());
        }
        //签名类型
        param.put("sign_type", "MD5");
        String sign = WxPayUtil.createSign("UTF-8", param, key);
        param.put("sign", sign);

        //封装参数为 xml;
        String xmlRequest = WxPayUtil.getRequestXml(param);
        System.out.println("微信支付请求参数---");
        System.out.println(xmlRequest);
        System.out.println("---");
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("text/xml; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());


        String result = restTemplate.postForObject(unifiedorderUri, xmlRequest, String.class);
//        result = new String(result.getBytes("ISO-8859-1"), "UTF-8");
        log.info("微信支付请求返回---");
        log.info(result);
        log.info("----");
        Map resultMap = XMLUtil.doXMLParse(result);
        UnfiedOrderResult unfiedOrderResult = JSONObject.parseObject(JSONObject.toJSONString(resultMap), UnfiedOrderResult.class);
        return unfiedOrderResult;

    }


    /***
     *  返回 微信支付二维码url
     * @param unfiedOrderParam
     * @param apiKey
     * @return
     */
    public static String unifiedorderForPC(UnfiedOrderParam unfiedOrderParam, String apiKey) {
        String url = null;
        UnfiedOrderResult unfiedOrderResult = null;
        try {
            unfiedOrderResult = unifiedorder(unfiedOrderParam, apiKey);
        } catch (Exception e) {
            e.printStackTrace();
            BizExceptionUtils.bizException("微信支付接口调用异常");
        }
        //返回状态码  处理
        if (ReturnCodeEnum.失败.getCode().equals(unfiedOrderResult.getReturn_code())) {
            BizExceptionUtils.bizException(unfiedOrderResult.getReturn_msg());
        }
        if (ReturnCodeEnum.成功.getCode().equals(unfiedOrderResult.getReturn_code()) && ReturnCodeEnum.失败.getCode().equals(unfiedOrderResult.getResult_code())) {
            BizExceptionUtils.bizException(unfiedOrderResult.getErr_code(), unfiedOrderResult.getErr_code_des());
        }
        if (ReturnCodeEnum.成功.getCode().equals(unfiedOrderResult.getReturn_code()) && ReturnCodeEnum.成功.getCode().equals(unfiedOrderResult.getResult_code())) {
            url = unfiedOrderResult.getCode_url();
        }
        return url;
    }


    /***
     * 回调函数校验
     *   若校验成功则 返回参数
     *   若校验失败 返回空
     * @param request
     * @param apiKey apiKey
     */
    public static PayNotifyResult checkPayCallBack(HttpServletRequest request, String apiKey) throws Exception {
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        //读取到的是xml,需要解析成map
        log.info("微信支付回调请求返回---");
        log.info(sb.toString());
        log.info("----");
        Map<String, String> resultMap = XMLUtil.doXMLParse(sb.toString());
        SortedMap<Object, Object> packageparams = new TreeMap<>();
        for (Object key : resultMap.keySet()) {
            String value = resultMap.get(key);
            String v = "";
            if (null != value) {
                v = value.trim();
            }
            packageparams.put(key, v);
        }
        //todo
        //验证签名是否正确
        if (WxPayUtil.isTenpaySign("UTF-8", packageparams, apiKey)) {
            PayNotifyResult payNotifyResult = JSONObject.parseObject(JSONObject.toJSONString(resultMap), PayNotifyResult.class);
            if (payNotifyResult == null) {
                return null;
            }
            if (ReturnCodeEnum.失败.getCode().equals(payNotifyResult.getResult_code())) {
                return null;
            }
            return payNotifyResult;

        } else {
            return null;
        }
    }

    /****
     * 响应微信支付通知
     * @param response response
     * @param isSuccess  回调函数校验 true 成功 false 失败
     * @throws IOException
     */
    public static void payCallBackResponse(HttpServletResponse response, boolean isSuccess, String tip) throws IOException {
        String resXml;
        if (true == isSuccess) {
            resXml = "<xml>"
                    + "<return_code><![CDATA[SUCCESS]]></return_code>"
                    + "<return_msg><![CDATA[OK]]></return_msg>"
                    + "</xml>";
        } else {
            resXml = "<xml>"
                    + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[" + tip + "]]></return_msg>"
                    + "</xml>";
        }
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();

    }
//    public static void main(String[] args) throws Exception {
//        UnfiedOrderParam unfiedOrderParam = new UnfiedOrderParam();
//        unfiedOrderParam.setAppid("wxd562bda39c913298");
//        unfiedOrderParam.setMch_id("1230000109");
//        unfiedOrderParam.setBody("测试-支付");
//        unfiedOrderParam.setTotal_fee(1);
//        unfiedOrderParam.setFee_type("CNY");
//        unfiedOrderParam.setSpbill_create_ip("192.168.0.1");
//        unfiedOrderParam.setNotify_url("notify_url/code");
//        unfiedOrderParam.setOpenid("DASDASF");
//        unfiedOrderParam.setTrade_type(WechatPayTradeTypeEnum.公众号支付.getCode());
//        unfiedOrderParam.setOut_trade_no("123123");
//        UnfiedOrderResult unfiedOrderResult  =unifiedorder(unfiedOrderParam,"89caf9a6901133c8fd72e699907a1248");
//        System.out.println(unfiedOrderResult);
//    }
}

